package com.express.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.express.dto.PasswordChangeRequest;
import com.express.dto.RegisterDto;
import com.express.dto.UserDto;
import com.express.entity.User;
import com.express.exception.BusinessException;
import com.express.exception.UserAlreadyExistsException;
import com.express.mapper.UserMapper;
import com.express.service.IUsersService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.express.propertise.JwtProperties;
import com.express.utils.BaseContext;
import com.express.utils.JwtUtil;
import com.express.vo.LoginVo;
import com.express.vo.UserInfoVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@Service
public class UsersServiceImpl extends ServiceImpl<UserMapper, User> implements IUsersService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private JwtProperties jwtProperties;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 用户登录
     *
     * @return
     */
    @Override
    public LoginVo login(UserDto userDto) {
        // 创建查询条件
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, userDto.getUserName());

        // 执行查询
        User user = userMapper.selectOne(queryWrapper);

        if (!Objects.equals(userDto.getUserName(), user.getUsername())) {
            throw new UserAlreadyExistsException("用户名错误");
        }
        // 校验用户是否存在以及密码是否匹配
        if (!user.getPassword().equals(DigestUtils.md5DigestAsHex(userDto.getPassword().getBytes()))) {
            throw new UserAlreadyExistsException("密码错误");
        }

        //登录成功后，生成jwt令牌
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", user.getUserId());
        String token = JwtUtil.createJWT(
                jwtProperties.getAdminSecretKey(),
                jwtProperties.getAdminTtl(),
                claims);
//        封装返回
        return LoginVo.builder()
                .userId(user.getUserId())
                .username(user.getUsername())
                .token(token).build();
    }

    /**
     * 用户注册
     *
     * @param registerDto
     */
    @Override
    public void register(RegisterDto registerDto) {
        // 检查用户名是否已存在
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, registerDto.getUsername());
        if (userMapper.selectOne(queryWrapper) != null) {
            throw new UserAlreadyExistsException("用户名已存在");
        }

        // 检查手机号是否已存在
        queryWrapper.clear();
        queryWrapper.eq(User::getPhoneNumber, registerDto.getPhoneNumber());
        if (userMapper.selectOne(queryWrapper) != null) {
            throw new UserAlreadyExistsException("手机号已存在");
        }

        // 检查邮箱是否已存在
        queryWrapper.clear();
        queryWrapper.eq(User::getEmail, registerDto.getEmail());
        if (userMapper.selectOne(queryWrapper) != null) {
            throw new UserAlreadyExistsException("邮箱已存在");
        }

        // 创建用户对象
        User user = new User();
        BeanUtils.copyProperties(registerDto, user);

        user.setCreatedAt(LocalDateTime.now());
        user.setUpdatedAt(LocalDateTime.now());

        // 加密密码
        user.setPassword(DigestUtils.md5DigestAsHex(user.getPassword().getBytes()));

        // 插入用户信息到数据库
        userMapper.insert(user);
    }

    /**
     * 获取用户信息
     *
     * @return
     */
    @Override
    public UserInfoVo getInfo() {
        Long userId = BaseContext.getCurrentId();
        User user = userMapper.selectById(userId);
        UserInfoVo userInfoVo = new UserInfoVo();
        BeanUtils.copyProperties(user, userInfoVo);
        return userInfoVo;
    }

    /**
     * 修改用户信息
     *
     * @param userInfoVo
     */
    @Override
    public void updateInfo(UserInfoVo userInfoVo) {
        User user = new User();
        BeanUtils.copyProperties(userInfoVo, user);
        user.setUserId(BaseContext.getCurrentId());
        user.setUpdatedAt(LocalDateTime.now());
        userMapper.updateById(user);
    }

    /**
     * 修改密码
     *
     * @param request
     */
    @Override
    @Transactional
    public void updatePassword(PasswordChangeRequest request) {
        //1.获取用户Id
        Long userId = BaseContext.getCurrentId();
        User user = this.getById(userId);

        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        //2.验证旧密码
        String oldPassword = DigestUtils.md5DigestAsHex(request.getOldPassword().getBytes());
        if (!user.getPassword().equals(oldPassword)) {
            throw new BusinessException("旧密码不正确");
        }
        //3.校验新密码复杂度
        validatePasswordPolicy(request.getNewPassword());
        //4.加密并更新密码
        String newPassword = DigestUtils.md5DigestAsHex(request.getNewPassword().getBytes());
        user.setPassword(newPassword);
        user.setUpdatedAt(LocalDateTime.now());

        userMapper.updateById(user);
    }

    /**
     * 密码策略验证
     */
    private void validatePasswordPolicy(String password) {
        // 修正正则表达式转义问题
        String pattern = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d).{8,16}$"; // 注意这里使用双反斜杠

        if (!password.matches(pattern)) {
            throw new BusinessException("密码需8-16位，包含大小写字母和数字");
        }
    }
}
